<script setup>
import Vrouter from "@/router"
import { ref, inject } from "vue"
import SparkMD5 from 'spark-md5'
import axios from "axios"
import { MYURL } from '@/utils/express/express.js'
import isToken from '@/utils/token/token.js'
import { lunchvideo } from '@/api/user/user.js'
import MyLoad from '@/components/MyLoad.vue'
// import { uploadvideo } from '@/api/user/user.js'
const change_success = inject('change_message_state')
const router = Vrouter
const title_count = ref(80)
const about_count = ref(150)
const change_title_count = (e) => {
    title_count.value < 0 ? title_count.value = 0 : title_count.value = 80 - e.target.value.length
}
const change_about_count = (e) => {
    about_count.value < 0 ? about_count.value = 0 : about_count.value = 150 - e.target.value.length
}
const about_input = ref(null)
const eidit_state = ref(false)
const chunk_size = 1024 * 1024 //定义每一片的大小
let hash
let file
const uploadState = ref(false)
let fd = new FormData()
const get_back = ref(null)
const load_state = ref(false)
const VIDEO_REG = /^(video\/)(.*)/
const upload_video = async (e) => {
    if (!e.target.files[0]) return change_success('请上传文件')
    if (!VIDEO_REG.test(e.target.files[0].type)) return change_success('请上传视频文件')
    if (uploadState.value) return change_success('请等待当前文件上传完毕')
    uploadState.value = true //设置当前是否正在上传
    upload_progress_state.value = true //设置进度条
    upload_progress_text.value = '上传中'
    upload_progress_percent.value = 0
    file = e.target.files[0]
    let video = document.createElement('video')
    video.preload = 'metadata'
    video.src = URL.createObjectURL(file)
    video.onloadedmetadata = () => {
        window.URL.revokeObjectURL(video.src)
        getVideoBase64(getFileURL(file), video.videoWidth, video.videoHeight).then(res => {
            setAddImg.value = res
            let blob = dataURLtoBlob(res)
            fd.set("image", blob)
            // let my_file = blobToFile(blob, 'image')
            // const reader = new FileReader()
            // reader.readAsDataURL(blob)          
            // reader.onload = (e) => {
            //     console.log(e.target.result);
            // }
        })
    }
    // 获取文件,并赋值到file
    // 开始分片
    let cut = 0 //分片下标
    let chunks = [] // 放切片
    while (cut < file.size) {
        const blob = file.slice(cut, cut + chunk_size)
        chunks.push(blob)
        cut += chunk_size
    }
    // console.log(chunk) chunk为切片完毕

    load_state.value = true
    // 开始计算hash值
    hash = await calc_hash(chunks)
    load_state.value = false

    await uploadChunks(chunks)
    if (file_state.value.have) return
    sb().catch(() => {
        uploadState.value = false
    })
    upload_progress_text.value = '上传成功'
    uploadState.value = false
    // change_success('上传成功')
}
const file_state = ref(true)
const uploadChunks = async (chunks) => {
    // 开始上传切片
    const data = await chunks.map((chunk, index) => {
        return {
            filehash: hash,
            chunkhash: hash + '-' + index,
            chunk
        }
    })
    const formDatas = await data.map((item) => {
        const formData = new FormData()
        formData.set('filehash', item.filehash)
        formData.set('chunkhash', item.chunkhash)
        formData.set('chunk', item.chunk)
        return formData
    })
    // console.log(formDatas) forDatas为上传文件
    const max = 3  // 定义最大并发数
    let index = 0  //定义上传时的下标
    const taskpool = [] //定义请求池
    const file_have = axios({
        headers: {
            'Authorization': isToken()
        },
        method: 'post',
        url: `${MYURL}/user/uploadhash`,
        data: {
            fileHash: hash,
            fileName: file.name,
            fileSize: file.size

        },
    }).then((res) => {
        return res.data
    })
    file_state.value = await file_have
    if (file_state.value.have) {
        if (file_state.value.status == 1) {
            upload_progress_state.value = false
            uploadState.value = false
            change_success('请上传小于1G的视频')
        } else {
            upload_progress_percent.value = 100
            uploadState.value = false
            // change_success('上传成功')
        }
        return
    }
    while (index < formDatas.length) {
        //     const task = axios({
        //         headers: {
        //             'Content-Type': 'multipart/form-data',
        //             'Authorization': isToken()
        //         },
        //         method: 'post',
        //         url: `${MYURL}/user/uploadVideo`,
        //         data: formDatas[index],
        //     })
        // taskpool.splice(taskpool.findIndex(async (item) => await item === task)
        //     taskpool.push(task)
        //     if (taskpool.length === max) {
        //         await Promise.race(taskpool)
        //     }

        // }

        taskpool.push(
            axios({
                headers: {
                    'Content-Type': 'multipart/form-data',
                    'Authorization': isToken()
                },
                method: 'post',
                url: `${MYURL}/user/uploadVideo`,
                data: formDatas[index],
            })
        )
        if (taskpool.length === max) {
            taskpool.splice(await Promise.race(taskpool))
        }
        index++
        upload_progress_percent.value = index / formDatas.length * 100
    }
    try {
        await Promise.all(taskpool)
    } catch (error) {
        upload_progress_state.value = false
        uploadState.value = false
        change_success('上传失败')
    }
}

// 做结尾校验的函数
const sb = async () => {
    axios({
        headers: {
            'Authorization': isToken()
        },
        method: 'post',
        url: `${MYURL}/user/merge`,
        data: {
            fileHash: hash,
            fileName: file.name,
            size: chunk_size
        },
    })
}
// 定义hash值计算方法
const calc_hash = (chunks) => {
    return new Promise(resolve => {
        // 开始计算hash值:
        const targets = [] //参与计算的所有切片
        // 计算规则:
        //     1.第一个切片和最后一个切片全部参与计算
        //     2. 中间的切片只计算前两个字节和中间两个字节和最后两个字节
        chunks.forEach((chunk, index) => {
            // 1.第一个切片和最后一个切片全部参与计算
            if (index === 0 || index === chunks.length - 1) {
                targets.push(chunk)
            } else {
                // 2. 中间的切片只计算前两个字节和中间两个字节和最后两个字节
                targets.push(chunk.slice(0, 2))
                targets.push(chunk.slice(chunk_size / 2, chunk_size / 2 + 2))
                targets.push(chunk.slice(chunk_size - 2, chunk_size))
            }
        })
        const spark = new SparkMD5.ArrayBuffer()
        const fileReader = new FileReader()
        fileReader.readAsArrayBuffer(new Blob(targets))
        fileReader.onload = (e) => {
            spark.append(e.target.result)
            resolve(spark.end())
        }
    })
}
const upload_progress_percent = ref(0)
const upload_progress_state = ref(false)
const upload_progress_text = ref('上传中')

//获取视频第一帧为视频封面
const getVideoBase64 = (url, mywidth, myheight) => {
    return new Promise(function (resolve) {
        let dataURL = '';
        let video = document.createElement("video")
        video.setAttribute('crossOrigin', 'anonymous') //处理跨域
        video.setAttribute('src', url);
        video.setAttribute('width', mywidth);
        video.setAttribute('height', myheight);
        video.setAttribute('autoplay', 'autoplay');
        video.addEventListener('canplaythrough', function () {
            let canvas = document.createElement("canvas"),
                width = video.width, //canvas的尺寸和图片一样
                height = video.height;
            canvas.width = width
            canvas.height = height
            canvas.getContext("2d").drawImage(video, 0, 0, width, height); //绘制canvas
            dataURL = canvas.toDataURL('image/jpeg'); //转换为base64
            video.pause()
            resolve(dataURL);
        })
    })
}

//获取视频url
const getFileURL = (file) => {
    var url = null;
    if (window.createObjectURL != undefined) { // basic
        url = window.createObjectURL(file);
    } else if (window.URL != undefined) { // mozilla(firefox)
        url = window.URL.createObjectURL(file);
    } else if (window.webkitURL != undefined) { // webkit or chrome
        url = window.webkitURL.createObjectURL(file);
    }
    return url;
}
import addImg from '@/assets/img/add.png'
const setAddImg = ref(addImg)
const video_image = ref(null)
const title_text = ref(null)
const lunch = async () => {
    if (!hash) return change_success('请上传视频哦')
    if (upload_progress_percent.value != 100) return change_success('请等待视频上传完毕哦')
    if (title_text.value === null) {
        change_success('请输入标题')
        return
    }
    fd.set('fileHash', hash)
    fd.set('about', about_input.value)
    fd.set('title', title_text.value)
    fd.set('fileName', file.name)
    lunchvideo(fd).then((res) => {
        if (res.data.status === 0) {
            router.go(-1)
        }
        change_success(res.data.mes)
    }).catch(() => {
        alert('文件上传失败')
    })
}


const dataURLtoBlob = (dataurl) => {
    var arr = dataurl.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new Blob([u8arr], { type: mime });
}
//将blob转换为file
// const blobToFile = (theBlob, fileName) => {
//     theBlob.lastModifiedDate = new Date();
//     theBlob.name = fileName;
//     return theBlob;
// }
</script>

<template>
    <MyLoad v-show="load_state">请稍后...</MyLoad>
    <div class="get-back-main">
        <img ref="get_back" class="back-image" @click="router.go(-1)" src="@/assets/img/getback.png">
        <div class="title">
            发布视频
        </div>
    </div>
    <div class="getback-placehoder"></div>
    <div v-if="upload_progress_state" class="upload_progress">
        <p>{{ upload_progress_text }}</p>
        <div :style="{ width: upload_progress_percent + '%' }" class="upload_progress_main"></div>
    </div>
    <div style="padding: 0 20px 10px 20px;">
        <div class="video-image">
            <div class="image-left">
                <img :src="setAddImg" ref="video_image">
                <input accept="video/*" @change="upload_video" type="file">
                <div v-show="eidit_state">
                    <img src="@/assets/img/bianjiwhite.png">
                    <p>修改封面</p>
                </div>
            </div>
            <div class="image-right">
                <textarea v-model="title_text" @input="change_title_count" placeholder="合适的标题可以吸引更多人观看~" maxlength="80"
                    id="" cols="30" rows="10"></textarea>
                <p>{{ title_count }}</p>
            </div>
        </div>
    </div>
    <div @click="about_input.focus" class="video-about">
        <p>简介</p>
        <img src="@/assets/img/getback.png" alt="">
    </div>
    <div style="padding: 0 20px;">
        <div class="video-about-edit image-right">
            <textarea v-model="about_input" @input="change_about_count" placeholder="填写简介让更多人发现吧~" maxlength="150" id=""
                cols="30" rows="10"></textarea>
            <p>{{ about_count }}</p>
        </div>
    </div>
    <div @click="lunch" class="lunch">
        <p>发布</p>
    </div>
</template>

<style lang="less" scoped>
.upload_progress {
    width: 100%;
    margin-top: 20px;
    height: 2px;
    background-color: rgba(0, 0, 0, 0.09);
    position: relative;

    .upload_progress_main {
        // width: 0;
        border-radius: 5px;
        height: 100%;
        background-color: var(--bilibili-pink);
    }

    p {
        position: absolute;
        left: 0;
        top: 0;
        transform: translate(50%, -100%);
        color: #696d73;
        font-size: 12px;
    }
}

.video-image {
    margin-top: 10px;
    display: flex;
    justify-content: space-around;
    align-items: flex-start;
    // padding: 0 20px;
    gap: 10px;
    border-bottom: 2px rgba(0, 0, 0, 0.09) solid;

    textarea {
        font-size: 12px !important;
        resize: none;
        border: none;
        outline: none;
        font-size: 14px;
        // width: 50vw;
        color: #696d73;
    }
}

.image-left {
    position: relative;

    input {
        position: absolute;
        width: 100%;
        height: 100%;
        left: 0;
        top: 0;
        opacity: 0;
    }

    // width: 50vw;
    img {
        width: 100%;
        object-fit: cover !important;

    }

    >div {
        background-color: rgba(0, 0, 0, 0.72);
        position: absolute;
        bottom: 0;
        left: 0%;
        display: flex;
        align-items: center;
        justify-content: center;
        // transform: translate(-50%,-100%);
        gap: 5px;
        white-space: nowrap;
        padding: 3px;
        // border-radius: 5px;
        width: 100%;
        color: white;
        font-size: 12px;

        img {
            width: 10%;
        }
    }
}

.image-right {
    position: relative;

    p {
        color: #696d73;
        font-size: 12px;
        position: absolute;
        bottom: 0;
        right: 0;
        transform: translate(-50%, -50%);
    }
}

.video-about {
    margin-top: 20px;
    align-items: center;
    display: flex;
    padding: 0 20px;
    font-weight: 600;

    img {
        margin-left: auto;
        width: 10px;
        transform: rotate(180deg);
    }
}

.video-about-edit {
    margin-top: 20px;
    width: 100%;

    textarea {
        width: 100%;
        border: none;
        outline: none;
        resize: none;
    }
}

.lunch {
    margin: 0 auto;
    // margin-top: 20px;
    width: 80%;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--bilibili-pink);
    padding: 10px 0;
    border-radius: 20px;
    color: white;
}
</style>